﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.IO;
using System.Drawing.Imaging;
using System.Threading;

using System.Runtime.InteropServices;
using System.Reflection;

namespace Pencil
{
    public partial class FormMain : Form
    {
        //定义List泛型集合对象，存储所有直线
        private List<Shape> _listShape = new List<Shape>();
        //保存当前绘制的临时图元
        private Shape _tempShape = null;
        //临时保存被撤销的图元
        private List<Shape> _listTempShape = new List<Shape>();
        //当前的绘图类型
        private DrawType _drawType = DrawType.Line;//默认为直线
        //保存当前绘图的线宽
        private int _drawWidth = 10;
        //保存当前绘图的颜色
        private Color _drawColor = Color.Red;
        //保存BufferredGraphicsContext对象，该对象用于分配和管理图形缓冲区
        BufferedGraphicsContext _bufGraphCont = null;
        //保存BufferredGraphics（图形缓冲区）对象
        BufferedGraphics _bufGraph = null;
        //保存当前图形的文件名（默认为空）
        private string _filename = "";
        //是否需要保存
        private Boolean _saveFlag = false;
        //保存图形缩放比例
        private double _zoomRatio = 1;
        //窗口的初始尺寸
        private Size _panelDrawInitSize = new Size(0, 0);
        //保存屏幕位图
        private Bitmap _screenBmp = null;
        //保存与屏幕位图相对应的Graphics对象
        private Graphics _screenBmpGraphics = null;
        
        //定义键盘消息结构体
        public struct KeyMSG
        {
            public int vkCode;   //键值虚拟码（1-254）
            public int scanCode; //硬件扫描码
            public int flags;    //键盘按下时间等于128，键盘抬起时等于0
            public int time;     //windows运行时间
            public int dwExtraInfo;
        }
        //定义变量
        public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
        static int hKeyboardHook = 0;
        HookProc KeyboardHookProcedure;

        //安装钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        //卸载钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        //继续下一个钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(int idHook,int nCode, Int32 wParam, IntPtr lParam);

        //钩子处理:就是钩子要做的事情
        private int KeyboardHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            { 
               //将IParam数据转换成键盘消息
                KeyMSG m = (KeyMSG)Marshal.PtrToStructure(lParam, typeof(KeyMSG));
                //如果按下F3键，则处理屏幕截屏,键盘按下时flags = 128,抬起是0
                if (m.flags == 0 && m.vkCode == (int)(Keys.F3))
                { 
                    //调用截屏响应事件
                    MenuItemScreenPen_Click(this, null);
                    return 1;
                }
                //返回0则表示消息出了这个钩子向下传递，也就是传给真正的钩子
                return 0;
            }
            return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
        }
        //安装钩子
        public void HookStart()
        {
            if (hKeyboardHook == 0)
            { 
                //创建HookProc事例
                KeyboardHookProcedure = new HookProc(KeyboardHookProc);
                //设置线程钩子
                hKeyboardHook = SetWindowsHookEx(13, KeyboardHookProcedure, Marshal.GetHINSTANCE(
                                Assembly.GetExecutingAssembly().GetModules()[0]), 0);
                //如果设置钩子失败
                if (hKeyboardHook == 0)
                {
                    HookStop();
                    throw new Exception("SetWindowsHookEx failed");
                }
            }
        }

        //卸载钩子
        public void HookStop()
        {
            bool retKeyboard = true;
            if (hKeyboardHook != 0)
            {
                retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
                hKeyboardHook = 0;
            }
            if (!(retKeyboard))
                throw new Exception("UnhookWindowsHookEx failed");
        }
        //构造方法
        public FormMain()
        {
            InitializeComponent();
            try
            {
                HookStart();
            }
            catch (Exception ex)
            {
                MessageBox.Show("钩子安装失败！提示消息：" + ex.Message);
            }
            //获取BufferredGraphicsContext对象，来消除图像重绘时的闪烁
            _bufGraphCont = BufferedGraphicsManager.Current;
            //使用和CreateGraphics一样的像素格式创建指定大小的图形缓存区
            _bufGraph = _bufGraphCont.Allocate(this.CreateGraphics(), this.ClientRectangle);
            //清空图形缓存区
            _bufGraph.Graphics.Clear(Color.White);
            //设置抗锯齿平滑模式
            _bufGraph.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        }
        private void FormMain_Load(object sender, EventArgs e)
        {
            //获取BufferredGraphicsContext对象，来消除图像重绘时的闪烁
            _bufGraphCont = BufferedGraphicsManager.Current;
            //使用和CreateGraphics一样的像素格式创建指定大小的图形缓存区
            _bufGraph = _bufGraphCont.Allocate(panelDraw.CreateGraphics(), panelDraw.ClientRectangle);
            //清空图形缓存区
            _bufGraph.Graphics.Clear(Color.White);
            //设置抗锯齿平滑模式
            _bufGraph.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            
            //获取屏幕宽度和高度
            int screenWidth = Screen.PrimaryScreen.Bounds.Width;
            int screeHeight = Screen.PrimaryScreen.Bounds.Height;
            //创建屏幕位图对象，其大小对屏幕大小对象
            _screenBmp = new Bitmap(screenWidth, screeHeight);
            //获取与屏幕位图相对应的Graphics对象
            _screenBmpGraphics = Graphics.FromImage(_screenBmp);
            //清除屏幕位图，并用白色填充
            _screenBmpGraphics.Clear(Color.White);

            //保存panelDraw初始尺寸
            _panelDrawInitSize.Width = panelDraw.Width;
            _panelDrawInitSize.Height = panelDraw.Height;
            //初始禁用撤销
            MenuItemUndo.Enabled = false;
            toolStripButtonUndo.Enabled = false;
            //初始禁用重做
            MenuItemRedo.Enabled = false;
            toolStripButtonRedo.Enabled = false;
            //以pencil.cur为源文件，创建一个cursor对象，并设置光标
            Cursor penCur = new Cursor("pencil.cur");
            this.Cursor = penCur;
            //把菜单条，工具条，状态条的光标设置成默认的箭头光标
            menuStrip1.Cursor = Cursors.Arrow;
            toolStrip1.Cursor = Cursors.Arrow;
            statusStrip1.Cursor = Cursors.Arrow;
        }
        //鼠标下压事件
        private void FormMain_MouseDown(object sender, MouseEventArgs e)
        {
            
        }
        //鼠标抬起事件
        private void FormMain_MouseUp(object sender, MouseEventArgs e)
        {
            
        }
        //鼠标移动的响应事件
        private void FormMain_MouseMove(object sender, MouseEventArgs e)
        {
            
        }
        //paint(窗口绘制事件响应方法)
        private void FormMain_Paint(object sender, PaintEventArgs e)
        {
            
        }
        //panelDraw鼠标下压
        private void panelDraw_MouseDown(object sender, MouseEventArgs e)
        {
            //判断是否在绘图
            if (_drawType != DrawType.Stop)
            {
                //绘制直线
                if (_drawType == DrawType.Line)
                {
                    _tempShape = new Line();
                    ((Line)_tempShape)._P1 = new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio));
                }
                //绘制矩形
                else if (_drawType == DrawType.Rectangle)
                {
                    _tempShape = new Rectangle();
                    ((Rectangle)_tempShape)._P1 = new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio));
                }
                else if (_drawType == DrawType.Circle)
                {
                    _tempShape = new Circle();
                    //圆心
                    ((Circle)_tempShape)._PCenter = new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio));
                }
                else if (_drawType == DrawType.Sketch)
                {
                    _tempShape = new Sketch();
                    ((Sketch)_tempShape)._PointList.Add(new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio)));
                }
                //保存图元的画笔宽度和颜色
                _tempShape._PenWidth = _drawWidth;
                _tempShape._PenColor = _drawColor;
            }
        }

        private void panelDraw_MouseMove(object sender, MouseEventArgs e)
        {
            //判断鼠标左键下压
            if (e.Button == MouseButtons.Left)
            {
                //判断是否在绘图
                if (_drawType != DrawType.Stop)
                {
                    //冲掉上个鼠标移动点的图元，鼠标移动时绘制的图元没必要加入到list中，鼠标再次移动时清除上次鼠标移动绘制的图元
                    _bufGraph.Graphics.Clear(Color.White);
                    //将屏幕位图绘制到图形缓冲区
                    _bufGraph.Graphics.DrawImage(_screenBmp, new Point(0, 0));
                    //将已经抬起绘制的图元重新加入缓冲区
                    foreach (Shape shape in _listShape)
                        shape.Draw(_bufGraph.Graphics, DashStyle.Solid, _zoomRatio);
                    //在当前鼠标位置绘制新图元
                    //根据绘图类型存到临时图元
                    if (_drawType == DrawType.Line)
                        ((Line)_tempShape)._P2 = new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio));
                    else if (_drawType == DrawType.Rectangle)
                        ((Rectangle)_tempShape)._P2 = new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio));
                    else if (_drawType == DrawType.Circle)
                        ((Circle)_tempShape)._R = (float)Math.Sqrt(Math.Pow(((int)(e.X / _zoomRatio) - ((Circle)_tempShape)._PCenter.X), 2) +
                                                         Math.Pow(((int)(e.Y / _zoomRatio) - ((Circle)_tempShape)._PCenter.Y), 2));
                    else if (_drawType == DrawType.Sketch)
                        ((Sketch)_tempShape)._PointList.Add(new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio)));
                    //绘制临时图元到缓存区
                    _tempShape.Draw(_bufGraph.Graphics, DashStyle.Dash, _zoomRatio);
                    //将缓存区绘制到当前窗口
                    _bufGraph.Render(panelDraw.CreateGraphics());
                }
            }
            //显示鼠标坐标
            StatusLabelMousePosistion.Text = "鼠标：x=" + e.X + ", y" + e.Y;
        }

        private void panelDraw_MouseUp(object sender, MouseEventArgs e)
        {
            //判断是否在绘图
            if (_drawType != DrawType.Stop)
            {
                if (_drawType == DrawType.Line)
                {
                    ((Line)_tempShape)._P2 = new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio));
                }
                else if (_drawType == DrawType.Rectangle)
                {
                    ((Rectangle)_tempShape)._P2 = new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio));
                }
                else if (_drawType == DrawType.Circle)
                {
                    ((Circle)_tempShape)._R = (float)Math.Sqrt(Math.Pow(((int)(e.X / _zoomRatio) - ((Circle)_tempShape)._PCenter.X), 2) +
                                                               Math.Pow(((int)(e.Y / _zoomRatio) - ((Circle)_tempShape)._PCenter.Y), 2));
                }
                else if (_drawType == DrawType.Sketch)
                    ((Sketch)_tempShape)._PointList.Add(new Point((int)(e.X / _zoomRatio), (int)(e.Y / _zoomRatio)));
                //加入到图元集合
                _listShape.Add(_tempShape);
                //设置保存标记为true
                _saveFlag = true;
                //清空临时撤销列表
                _listTempShape.Clear();
                //禁用
                MenuItemRedo.Enabled = false;
                toolStripButtonRedo.Enabled = false;
                //启用撤销菜单
                MenuItemUndo.Enabled = true;
                toolStripButtonUndo.Enabled = true;
                //清空图形缓冲区
                _bufGraph.Graphics.Clear(Color.White);
                //将屏幕位图绘制到图形缓冲区
                _bufGraph.Graphics.DrawImage(_screenBmp, new Point(0, 0));
                //绘制到缓存区
                foreach (Shape shape in _listShape)
                    shape.Draw(_bufGraph.Graphics, DashStyle.Solid, _zoomRatio);
                //显示到主窗口
                _bufGraph.Render(panelDraw.CreateGraphics());
            }
        }

        private void panelDraw_Paint(object sender, PaintEventArgs e)
        {
            //清空图形缓冲区
            _bufGraph.Graphics.Clear(Color.White);
            //将屏幕位图绘制到缓冲区
            _bufGraph.Graphics.DrawImage(_screenBmp, new Point(0, 0));
            //绘制所有图元到缓冲区
            foreach (Shape shape in _listShape)
                shape.Draw(_bufGraph.Graphics, DashStyle.Solid, _zoomRatio);
            //将图形绘制到主窗口
            _bufGraph.Render(e.Graphics);
        }
        //直线菜单的响应
        public void MenuItemLine_Click(object sender, EventArgs e)
        {
            //排他，给自己加checked
            MenuItemLine.Checked = true;
            MenuItemRectangle.Checked = false;
            MenuItemCircle.Checked = false;
            MenuItemSketch.Checked = false;
            MenuItemStop.Checked = false;
            _drawType = DrawType.Line;
        }
        //矩形菜单的响应
        public void MenuItemRectangle_Click(object sender, EventArgs e)
        {
            MenuItemLine.Checked = false;
            MenuItemRectangle.Checked = true;
            MenuItemCircle.Checked = false;
            MenuItemSketch.Checked = false;
            MenuItemStop.Checked = false;
            _drawType = DrawType.Rectangle;
        }
        //圆形菜单的响应
        public void MenuItemCircle_Click(object sender, EventArgs e)
        {
            MenuItemLine.Checked = false;
            MenuItemRectangle.Checked = false;
            MenuItemCircle.Checked = true;
            MenuItemSketch.Checked = false;
            MenuItemStop.Checked = false;
            _drawType = DrawType.Circle;
        }
        //徒手画选项响应
        public void MenuItemSketch_Click(object sender, EventArgs e)
        {
            MenuItemLine.Checked = false;
            MenuItemRectangle.Checked = false;
            MenuItemCircle.Checked = false;
            MenuItemSketch.Checked = true;
            MenuItemStop.Checked = false;
            _drawType = DrawType.Sketch;
        }

        //停止菜单的响应
        private void MenuItemStop_Click(object sender, EventArgs e)
        {
            MenuItemLine.Checked = false;
            MenuItemRectangle.Checked = false;
            MenuItemCircle.Checked = false;
            MenuItemSketch.Checked = false;
            MenuItemStop.Checked = true;
            _drawType = DrawType.Stop;
        }
        //颜色菜单的响应事件
        public void MenuItemColor_Click(object sender, EventArgs e)
        {
            //设置颜色对话框的默认选中的颜色
            colorDialog1.Color = _drawColor;
            //显示颜色对话框，并判断是否按了ok按钮
            if (colorDialog1.ShowDialog(this) == DialogResult.OK)
            { 
                //保存用户选择的颜色
                _drawColor = colorDialog1.Color;
            }
        }
        //线宽菜单的点击事件
        public void MenuItemWidth_Click(object sender, EventArgs e)
        {
            //新建一个线宽对话框
            DlgPenWidth dlfPenWidth = new DlgPenWidth();
            //设置默认宽度
            dlfPenWidth._PenWidth = _drawWidth;
            //显示线宽对话框，并判断是否按了ok按钮
            if (dlfPenWidth.ShowDialog(this) == DialogResult.OK)
            { 
                //保存线宽
                _drawWidth = (int)(dlfPenWidth._PenWidth);
            }
        }
        //撤销点击事件
        public void MenuItemUndo_Click(object sender, EventArgs e)
        {
            //判断是否有图元
            if (_listShape.Count != 0)
            {
                //删除前存到撤销list中
                _listTempShape.Add(_listShape[_listShape.Count - 1]);
                //删除最后一个图元
                _listShape.RemoveAt(_listShape.Count - 1);
                //清空缓冲区
                _bufGraph.Graphics.Clear(Color.White);
                //重新绘制到缓冲区
                foreach (Shape shape in _listShape)
                    shape.Draw(_bufGraph.Graphics, DashStyle.Solid, _zoomRatio);
                //将缓冲区内容1绘制到主窗口
                _bufGraph.Render(panelDraw.CreateGraphics());
                //是否禁用撤销
                if (_listShape.Count == 0)
                {
                    MenuItemUndo.Enabled = false;
                    toolStripButtonUndo.Enabled = false;
                }
                //启用重做菜单
                MenuItemRedo.Enabled = true;
                toolStripButtonRedo.Enabled = true;
                //设置保存标记为true
                _saveFlag = true;
            }
        }
        //重做点击事件
        private void MenuItemRedo_Click(object sender, EventArgs e)
        {
           //撤销临时列表有数据
            if (_listTempShape.Count != 0)
            {
                //加到图元集合中
                _listShape.Add(_listTempShape[_listTempShape.Count - 1]);
                //从撤销集合中取出
                _listTempShape.RemoveAt(_listTempShape.Count - 1);
                //清空缓冲区
                _bufGraph.Graphics.Clear(Color.White);
                //重新绘制
                foreach (Shape shape in _listShape)
                    shape.Draw(_bufGraph.Graphics, DashStyle.Solid, _zoomRatio);
                _bufGraph.Render(panelDraw.CreateGraphics());
                //判断是否禁用重做
                if (_listTempShape.Count == 0)
                {
                    MenuItemRedo.Enabled = false;
                    toolStripButtonRedo.Enabled = false;
                }
                //启用撤销
                MenuItemUndo.Enabled = true;
                toolStripButtonUndo.Enabled = true;
                //设置保存标记为true
                _saveFlag = true;
            }
        }
        //线宽设置
        private void ToolStripMenuItem1px_Click(object sender, EventArgs e)
        {
            _drawWidth = 1;
        }

        private void ToolStripMenuItem2px_Click(object sender, EventArgs e)
        {
            _drawWidth = 2;
        }

        private void ToolStripMenuItem4px_Click(object sender, EventArgs e)
        {
            _drawWidth = 4;
        }

        private void ToolStripMenuItem8px_Click(object sender, EventArgs e)
        {
            _drawWidth = 8;
        }

        private void ToolStripMenuItemRed_Click(object sender, EventArgs e)
        {
            _drawColor = Color.Red;
        }

        private void ToolStripMenuItemGreen_Click(object sender, EventArgs e)
        {
            _drawColor = Color.Green;
        }

        private void ToolStripMenuItemBlue_Click(object sender, EventArgs e)
        {
            _drawColor = Color.Blue;
        }

        private void ToolStripMenuItemYellow_Click(object sender, EventArgs e)
        {
            _drawColor = Color.Yellow;
        }

        private void ToolStripMenuItemBlack_Click(object sender, EventArgs e)
        {
            _drawColor = Color.Black;
        }
        //新建
        private void MenuItemNew_Click(object sender, EventArgs e)
        {
            //保存标记为true，进行提醒
            if (_saveFlag == true)
            { 
                //弹出保存提示框
                if (MessageBox.Show("图形已经改变，您需要保存吗", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    MenuItemSave_Click(null, null);   
            }
            //清空_listShape中的所有图元
            _listShape.Clear();
            //清空_listTempShape的所有图元
            _listTempShape.Clear();
            //清空图形缓冲区
            _bufGraph.Graphics.Clear(Color.White);
            //将缓冲区绘制到当前窗口
            _bufGraph.Render(panelDraw.CreateGraphics());

            //清空当前图形的文件名
            _filename = "";
            //设置窗口标题
            this.Text = "画笔-无标题";
            //禁用撤销和重做按钮及菜单
            MenuItemUndo.Enabled = false;
            toolStripButtonUndo.Enabled = false;
            MenuItemRedo.Enabled = false;
            toolStripButtonRedo.Enabled = false;
            //设置保存标记为false
        }
        //打开
        private void MenuItemOpen_Click(object sender, EventArgs e)
        {
            //显示文件打开对话框
            if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
            { 
               //调用新建的点击事件
                MenuItemNew_Click(null, null);
                //保存用户选择的文件名
                _filename = openFileDialog1.FileName;
                //设置窗口标题
                this.Text = "画笔" + _filename;
                //创建一个文件流对象，用于读出图形信息
                FileStream fs = new FileStream(_filename, FileMode.Open, FileAccess.Read);
                //创建一个与文件流对象相对应的二进制读入流对象
                BinaryReader br = new BinaryReader(fs);
                //从文件中读取图元数量
                int shapeCount = br.ReadInt32();
                //从文件中读取图元信息
                for (int i = 0; i < shapeCount; i++)
                { 
                    //读出图元类型
                    string ShapeType = br.ReadString();
                    if (ShapeType == "Pencil.Line")
                    {
                        Line shape = new Line();
                        shape.Read(br);
                        _listShape.Add(shape);
                    }
                    else if (ShapeType == "Pencil.Rectangle")
                    {
                        Rectangle shape = new Rectangle();
                        shape.Read(br);
                        _listShape.Add(shape);
                    }
                    else if (ShapeType == "Pencil.Circle")
                    {
                        Circle shape = new Circle();
                        shape.Read(br);
                        _listShape.Add(shape);
                    }
                    else if (ShapeType == "Pencil.Sketch")
                    {
                        Sketch shape = new Sketch();
                        shape.Read(br);
                        _listShape.Add(shape);
                    }
                    else
                        MessageBox.Show("图元类型错误", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                //关闭有关文件流对象
                br.Close();
                fs.Close();
                //设置保存标记为false
                _saveFlag = false;
                //清空图形缓冲区
                _bufGraph.Graphics.Clear(Color.White);
                //逐一绘制图元到缓冲区
                foreach (Shape shape in _listShape)
                    shape.Draw(_bufGraph.Graphics, DashStyle.Solid, _zoomRatio);
                //将缓冲区的图元绘制到当前窗口
                _bufGraph.Render(panelDraw.CreateGraphics());
            }
        }
        //保存
        private void MenuItemSave_Click(object sender, EventArgs e)
        {
            //如果_fileName为空，则需要弹出文件对话框设定文件名
            if (_filename == "")
            {
                //显示对话框
                if (saveFileDialog1.ShowDialog(this) == DialogResult.OK)
                {
                    //保存文件名
                    _filename = saveFileDialog1.FileName;
                    //设置窗口标题
                    this.Text = "画笔-" + _filename;
                }
                else
                    return;
            }
            //创建一个文件流对象，用于写入图形信息
            FileStream fs = new FileStream(_filename, FileMode.Create);
            //创建一个与文件流对象相对应的二进制写入流对象
            BinaryWriter bw = new BinaryWriter(fs);
            //将图元数量写入文件
            bw.Write(_listShape.Count());
            //将图元信息写入到文件
            foreach (Shape tempShape in _listShape)
            { 
                //存图元类型
                bw.Write(tempShape.GetType().ToString());
                //存信息
                tempShape.Write(bw);
            }
            //关闭文件流对象
            bw.Close();
            fs.Close();
            //设置保存标记为false
            _saveFlag = false;
        }
        //另存为
        private void MenuItemSaveAs_Click(object sender, EventArgs e)
        {
            //显示文件保存对话框，并设置另存的文件名
            if(saveFileDialog1.ShowDialog(this) == DialogResult.OK)
            {
                //保存用户设置的文件名
                _filename = saveFileDialog1.FileName;
                //设置窗口标题
                this.Text = "画笔" + _filename;
                //创建一个文件流对象，用于写入图形信息
                FileStream fs = new FileStream(_filename, FileMode.Create);
                //创建一个与文件流对象相对应的二进制写入流对象
                BinaryWriter bw = new BinaryWriter(fs);

                //把图元数量写入文件
                bw.Write(_listShape.Count());
                //逐一把图元信息写入到文件
                foreach (Shape tempShape in _listShape)
                { 
                    //把图元类型写入到文件
                    bw.Write(tempShape.GetType().ToString());
                    //把图元信息写入到文件
                    tempShape.Write(bw);
                }
                bw.Close();
                fs.Close();
                //设置保存标记为false
                _saveFlag = false;
            }
        }

        private void MenuItemSaveAsPic_Click(object sender, EventArgs e)
        {
            //显示图片保存对话框，设置需要保存的文件名
            if (saveFileDialog2.ShowDialog(this) == DialogResult.OK)
            { 
                //创建一个位图对象，其尺寸和窗体客户区尺寸相等
                Bitmap bitmap = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
                //获取位图的Graphics对象
                Graphics gBitmap = Graphics.FromImage(bitmap);
                //将图形缓冲区写入位图的Graphics对象
                _bufGraph.Render(gBitmap);
                //获取保存文件的后缀名
                string extension = System.IO.Path.GetExtension(saveFileDialog2.FileName);

                //根据后缀名，存储为相应格式的图片
                if (extension == ".jpg")
                    bitmap.Save(saveFileDialog2.FileName, ImageFormat.Jpeg);
                else if (extension == ".gif")
                    bitmap.Save(saveFileDialog2.FileName, ImageFormat.Gif);
                else if (extension == "bmp")
                    bitmap.Save(saveFileDialog2.FileName, ImageFormat.Bmp);
                else
                    MessageBox.Show("对不起，暂不支持该图片格式", extension, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void MenuItemClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            //如果保存标记为true，则显示保存
            if (_saveFlag == true)
            {
                if (MessageBox.Show("图形已经改变，您需要保存吗", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    MenuItemSave_Click(null, null);
            }
        }
        //放大
        private void MenuItemZoomIn_Click(object sender, EventArgs e)
        {
            //保存放大比例
            _zoomRatio = _zoomRatio * 1.1;
            //保存窗口的高度和宽度
            panelDraw.Width = (int)(_panelDrawInitSize.Width * _zoomRatio);
            panelDraw.Height = (int)(_panelDrawInitSize.Height * _zoomRatio);
            //使用与panelDraw相同的像素格式来创建指定大小的图形缓冲区
            _bufGraph = _bufGraphCont.Allocate(panelDraw.CreateGraphics(), panelDraw.ClientRectangle);
            //设置抗锯齿平滑模式
            _bufGraph.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            //清空缓冲区
            _bufGraph.Graphics.Clear(Color.White);
            //逐一绘制所有图元到缓冲区
            foreach (Shape shape in _listShape)
                shape.Draw(_bufGraph.Graphics, DashStyle.Solid, _zoomRatio);
            _bufGraph.Render(panelDraw.CreateGraphics());
        }
        //缩小
        private void MenuItemZoomOut_Click(object sender, EventArgs e)
        {
            //保存缩放比例
            _zoomRatio = _zoomRatio * 0.9;
            //保存窗口的高度和宽度
            panelDraw.Width = (int)(_panelDrawInitSize.Width * _zoomRatio);
            panelDraw.Height = (int)(_panelDrawInitSize.Height * _zoomRatio);
            //使用与panelDraw相同的像素格式来创建指定大小的图形缓冲区
            _bufGraph = _bufGraphCont.Allocate(panelDraw.CreateGraphics(), panelDraw.ClientRectangle);
            //设置抗锯齿平滑模式
            _bufGraph.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            //清空缓冲区
            _bufGraph.Graphics.Clear(Color.White);
            foreach (Shape shape in _listShape)
                shape.Draw(_bufGraph.Graphics, DashStyle.Solid, _zoomRatio);
            //逐一绘制所有图元到缓冲区
            _bufGraph.Render(panelDraw.CreateGraphics());
        }
        //屏幕画笔
        private void MenuItemScreenPen_Click(object sender, EventArgs e)
        {
           //判断是否处于画笔，以免重复按F3,(通过是否有边框)
            if (this.FormBorderStyle != FormBorderStyle.None)
            {
                //最小化当前窗口
                this.WindowState = FormWindowState.Minimized;
                //隐藏窗口所有界面
                menuStrip1.Visible = false;
                toolStrip1.Visible = false;
                statusStrip1.Visible = false;
                //设置窗口无边框
                this.FormBorderStyle = FormBorderStyle.None;
                //当前线程暂停300毫秒
                Thread.Sleep(300);
                //最大化窗口
                this.WindowState = FormWindowState.Maximized;

                //创建绘画工具框窗口
                DlgDrawTools myDlgDrawTools = new DlgDrawTools();
                //设置myDlgDrawTools为主窗口
                myDlgDrawTools._formMain = this;
                //将绘画工具箱显示为模态对话框
                myDlgDrawTools.Show();
                //获取屏幕高度和宽度
                int screenWidth = Screen.PrimaryScreen.Bounds.Width;
                int screenHeight = Screen.PrimaryScreen.Bounds.Height;

                //把屏幕拷贝到屏幕位图
                _screenBmpGraphics.CopyFromScreen(0, 0, 0, 0, new Size(screenWidth, screenHeight));

                //设置panelDraw窗口的宽度和高度等于屏幕的高度和宽度
                panelDraw.Width = screenWidth;
                panelDraw.Height = screenHeight;

                //设置图形缩放比例为默认值1
                _zoomRatio = 1;
                //设置panelDraw的初始尺寸
                _panelDrawInitSize = new Size(panelDraw.Width, panelDraw.Height);

                //创建指定大小的图形缓冲区，且像素格式和panelDraw.CreateGraphics的像素格式相同
                _bufGraph = _bufGraphCont.Allocate(panelDraw.CreateGraphics(), panelDraw.ClientRectangle);
                //设置抗锯齿
                _bufGraph.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                //清空图形缓冲区
                _bufGraph.Graphics.Clear(Color.White);
                //将屏幕位图绘制到图形缓冲区
                _bufGraph.Graphics.DrawImage(_screenBmp, new Point(0, 0));
                //将缓冲区绘制到panelDraw窗口
                _bufGraph.Render(panelDraw.CreateGraphics());
            }
        }
    }
}
